I think Cohen's reacting in part to the Grokster decision. There and in Betamax it came down to two points: whether legal uses existed and whether the maker encouraged illegal uses or not. For a while, if the RIAA tried to come after the BitTorrent protocol itself on the first point they'd've had to overcome the use of BitTorrent to distribute things like Linux distributions (which is a perfectly legal use). Now if they try to use the same arguments against Cohen that they used against Grokster, arguing he's encouraging illegal uses himself, they're going to have to overcome this contract with the MPAA that binds him to doing exactly the opposite. I think he's being a very smart cookie, looking at the legal arguments people like the RIAA might use to attack him as creator of the protocol and reference implementation and making sure he's got as many legal obstacles in any attacker's way as possible.
That's almost any restaurant. Most of them get "restaurant blend" coffee from places like Folgers or Hills Brothers. Anything that out of the bag is a mix of light brown and tan is not good coffee.
Far from it. The CEO was a bit stuck on dress, but not to the point of letting it override common sense or a million or so dollars a year in revenue. Of course it might've been another matter if the equipment hadn't worked perfectly for the demo, but I had no intention of letting that happen.
I eventually did leave the company, but it was 4 years later and because I had an offer that I liked a lot better (by that point I was getting real tired of Utah).
I had the CEO of a company I was working at start to gripe about my ignoring the dress code. I pointed at the pile of dirt and dust and dead insects that'd fallen out of the ceiling tile I'd pulled aside to work up in there and asked him if he was willing to get into that wearing his suit? He said no way, it was too expensive to ruin. I asked him if he was going to pay if I ruined my good clothes in there? He said no. "Then why should I? Now, can I get back to finding and fixing this wiring problem, or do you want the demo you're doing this afternoon, the one you said was critical to the company's success this year, to flop when none of the stuff you want to show off actually works?".
Which are, at least to me, just as easily spotted by the opening brace, or the changed indentation on the next line. Or by the font change for the keyword with any decent editor.
And grep or regexp search in Emacs recognize font changes how?:) The distinction is as much for "make it easy to programmatically find all occurrences of a call to f(...) without getting false hits on "if (... )"" as it is for "let a human pick out the if statements".
As someone with 20+ years of professional programming under my belt, a lot of it doing maintenance and enhancement of existing code, I'll say this: most of what's considered "coding standards" doesn't much matter. Indentation, brace positioning, type prefixes on variables, underlines vs. StudlyCaps, capitalization in general, most competent programmers can pick up on any variation quickly. The few things that count are more general:
Comment logic and motivation, not the code itself. I can figure out what the code's doing. What I need coming into it's what it's supposed to be doing, why the code does things the way it does, what the data structures are supposed to represent and how they're supposed to be used. On routines, tell me what the routine's supposed to accomplish, what arguments it takes in and what results it spits out (including error conditions).
Make variable names descriptive. Abbreviate where it makes sense, but make the name give me an idea of what it's for. It's less important that I know it's a string than that I know it's the last name of the customer whose order you're processing. And if all it's for is the index in a loop and it's got no meaning outside of the loop, then yes i and j are perfectly legitimate names that any programmer will (or should, at least) recognize.
Programmers should try to use consistent indentation, brace alignment and other formatting things when writing new code, and should try to match the existing formatting when modifying code. Emacs and other modern editors can do automatic indentation and pretty-printing for you, make use of those features and make it easy for programmers to set their editors up to match commonly-used styles. And make them clean up garbage, things like trailing whitespace and irregular alignment are disproportionate pains. I don't care much what the tab interval is, but I hate it when the interval changes every few lines.
Use whitespace for readability. Code like if(strlen(obj.getname())" is legal, but it's a lot harder to read than "if ( strlen( obj.getname() ) ". It also makes it easier to distinguish functions ("f(x)") from control structures ("if ( x )"). Similarly, putting the opening brace of a loop or conditional on the end of the line may be compact, but it makes it hard to distinguish the start of a multi-line body from a single-line body followed by some lines with the wrong indentation.
A few small formatting things are overall useful. Symbolic constants should be immediately recognizable as such and all-caps is a commonly-recognized way of doing that, for example. And the indentation level of the code should match the logical level, that is the "then" and "else" bodies of an if statement should be indented further than the "if" and "else" keywords (which should both be indented at the same level).
Robert Morris didn't intend his little worm program to spread as widely as it did, but none of the companies and universities whose networks were shut down by the Morris Worm in 1988 cared about intentions. They only cared about the fact that the worm killed their networks. When Sony's software starts playing games with my system I don't care what their intentions were, only what the results are.
That's not a typical modern server or end user application.
You mean a modern network server doesn't have to read data from it's incoming connections? News to me, every one I've worked on has that as one of it's primary tasks. And it can't process the data until it's read it (or at least a sufficient portion of it to be able to figure out what to do next). Now, you can get fancy by trying to multiplex multiple connections in a single thread, but it's much simpler to spawn one thread of execution for each connection. You've got enough complexity already that you don't need to go creating any more for yourself.
That most programs today aren't GUI applications where the UI should not be *blocked* whilst some request is processed?
Modern GUI applications are message-driven. It's the message-processing loop that needs to never block. If you look, you'll find that 90% of the code in that GUI application is plain old traditional synchronous code to handle each type of message. Only a small portion in the message loop actually deals with controlling multiple threads.
As an example, if a GUI event triggers a time-consuming compute process, I can do two things. One, I can spawn off a thread to do the compute job and signal me when it's done. Two, I can write the data block down a pipe and let another thread or process deal with it, after having set a monitor on the pipe so I'll get a message when data's available on it. When the data-available message comes in, I snarf the results back from the pipe and do what needs done with them. Depending on how I implement the compute job there may be a layer to handle multiple incoming requests and fire off compute jobs, but the big function that actually does the crunching will be plain old single-threaded synchronous code and I'll let the system scheduler handle multi-tasking between the various jobs running at any given time. And on a Unix system where fork/exec is relatively cheap, why waste development time on a complex multi-threaded compute program when I can design a simple single-threaded one that reads it's input from standard input (connected to the incoming pipe) and writes it's output to standard output (connected to the outgoing pipe) and is pretty much immune to memory leaks, memory corruption and a host of other problems caused by other threads of execution in the same address space. On a modern Unix this'll probably handle 50 or so forks/second, and I've the option of doing pre-forking and having one instance handle multiple requests before terminating which should net me a hundred or so requests/second easily. By my standards that's hideously slow, but it's more than sufficient for an awful lot of applications. Especially in user-interface applications, because humans simply can't handle hundreds of operations per second.
You're misreading. It's not 90% of the problems out there, it's 90% of the code in a given program that's synchronous. Take, for example, the process of reading data from a single input source and processing it. With no other input sources to look at, and no processing that doesn't require the data you're trying to read, exactly what can the code do while the read's completing? If it can't do anything, then doing the read in it's own thread is pointless. You incur the overhead of creating a thread, and then the parent simply blocks until the child thread completes. Less overhead to simply do the read in the same thread as a simple function call. When calculating the sine of an argument, what do you gain from doing that function in it's own thread since the caller needs the result before it can continue with whatever calculation it's doing? Most of a program is like that: the caller can't proceed until the function it's called returns it's results, so running the called function in a seperate thread doesn't actually result in any parallelization.
As for what I've been writing, the last decade or so it's been primarily highly-parallel high-performance applications. Juggling a few dozen serial I/O channels with sub-millisecond response times on each channel, with a mix of polled and non-polled protocols. Breaking that one down to one single-threaded process per I/O channel and using message-based IPC to pass data between the I/O processes and the main program roughly tripled it's capacity while slashing code complexity by an order of magnitude. Another one involved a network server capable of handling several hundred simultaneous requests and several thousand requests per second sustained. Shared config data was the big constraint there, we could've cut 20% in interlock overhead alone if we could've gone to seperate processes and improved stability in the process, but while Linux could spawn processes that fast Solaris couldn't (we needed to support both) and with a gig or so of config data we couldn't afford the memory split that happened when we did a config reload under maximum load. I think it took my replacement 6 months or so to finally realize that no, he can't short-cut the interlocking even if it does work OK that way in testing, what works with 1-2 simultaneous threads will not work with 1-2 hundred.
Even between threads you've got overhead, either true context-switch overhead (on systems with a 1:1 thread-to-KSE mapping) or a similar amount of thread-scheduler overhead (on systems with an N:1 thread-to-KSE mapping). Note that multiple processes will also use all available CPUs in a multi-processor system, and on some systems threads can only> execute on the single CPU their KSE is currently running on, so depending on your threads implementation a multi-threaded app may or may not use all CPUs.
As for the first part, as I noted a lot of "shared" memory is read-only as far as the child's concerned. The only real issue with seperate processes is the potential for a massive memory split if one process suddenly updates the majority of that "read-only" memory (eg. reloading of configuration data). Where you have lots of memory shared that doesn't involve pointer-based data structures, shared memory will get you what you need without the need for fully-shared address space (which means your various processes are protected from heap corruption by their siblings, among other things). There are times you need the entire address space shared, but IMHO they aren't nearly as common as they're made out to be and the problems of fully-shared address space are well-known and not insignificant.
As far as why you don't make every function a process, for the same reason you don't make every function a thread: the vast majority of a program is not parallelizable. Parallel threads of execution, be they threads or processes, are applicable when the parent can fire off the child and go do something else while the child executes. If the only thing the parent can do at that point is wait for the child to finish, it's more efficient to simply do a call within the same thread of execution.
Forked processes do share memory (at least until it's modified). What you get with a shared memory space is the requirement for a lot of mutexing to avoid multiple updates, and a massively increased chance of corrupting memory across all threads. Been there, done that, in spades. Having done several massively-multi-threaded applications, my evaluation is that 90% of the time you're probably better off avoiding memory-based communication entirely in favor of message-passing through pipes, sockets or similar IPC mechanisms. That has the advantage of also removing most of the interlocking needed for high-performance shared-memory designs. The exceptions are when you've got a large amount of common configuration data that all tasks need access to. Using mmap() is a better way of handling that than sharing the entire address space, but when you've got pointer-based structures the workarounds for variable base addresses can get hairy enough to make shared-address-space the better option.
Just my opinion, but after 25 years of making machines with bits for brains do things I'm inclined to trust my own judgement.
You need to upgrade to a current version of GDB, then. Anything recent (within the last year or two) handles threads fine. I've used it to debug applications with a couple of hundred simultaneously-active threads without any problems.
Exactly. NT got it's process model from VMS, and process creation was a very heavyweight operation. Unix, by contrast, had a very lightweight process creation operation. Hence NT needed threads to provide a faster alternative to processes, while Unix (whose processes were almost as cheap to create as NT threads) didn't really need threads for anything other than a marketing checklist (about the only thing Unix threads get you that processes don't is fully-shared address space, and I'd argue that's often more a problem than an advantage).
First, IPv6 is even easier to set up. You don't need DHCP for automatic address assignment, a device can get it's network number via broadcast and assign it's own address based on MAC address. Literally plug-and-play.
The way IPv6 addresses are (supposed to be) assigned makes NAT unneccesary. This makes things like instant-messaging and P2P protocols, where clients act as servers and really need public addresses to work smoothly, much easier to deal with. No kludging forwarding rules.
NAT can still be used where appropriate. You'll simply need it less often.
At the routing level it simplifies things because the address hierarchy can mirror the physical topology. This is invisible to end users, but it's a major major win at the ISP and backbone level. Especially when devices can be configured to automatically adapt to changing network numbers, which essentially eliminates network renumbering when connections change.
IPv4 and IPv6 seem to play together well. My desktop system is a hybrid IPv4/6 box defaulting to IPv6, my central router's IPv4-only. On the desktop box all the apps see IPv6-based sockets and the appropriate IPv4-over-IPv6 addresses, the IPv4 portions of the network see plain IPv4 traffic.
As a final note, when I replace my desktop and rebuild the central router, I'm going to go to an IPv6-based network with IPv4 support being secondary. Even with the need to NAT to a single IPv4 address on the external connection, I expect the whole thing to be relatively seamless.
Actually that would be wrong. California never adopted the UCITA, so absent any other agreement the transaction's governed by the Uniform Commercial Code. I never signed any agreement to only license the software before the sale, so an over-the-counter sale occurred per the UCC. I own the copy I bought under those rules. I'd also note that the appeals court considered the same logic you're using and explicitly rejected it in their ruling when they discussed whether formal title was needed or not.
My thought: Microsoft is trying to get Federal rules that they can live with and that'll override more restrictive state rules. Take a look at opt-in vs. opt-out in their proposal. They advocate opt-in for a very limited class of data that they know the general public's getting touchy about, and I'll bet they make that a headline point. But for all other classes of data, they want opt-out enshrined in law in a way that prevents any state from requiring opt-in across the board. And once this is nailed down in Federal law, it'll be all but impossible to get it changed later no matter what happens.
I think that's Microsoft's strategy: cave in on the few points the public's riled up about right now, while simultaneously nailing down favorable terms everywhere else.
I think the objection isn't to the taxation so much as to the fact that you could wind up liable for taxes on the same income in two states at the same time, which seems fundamentally unreasonable.
Well, for total identity theft you probably need the SSN. However, a lot can be done without the SSN. Given someone's name, address and birthdate you can get a forged driver's license that'll fool most clerks. If you also have their driver's license number, it'll fool most electronic checking systems as well. Know their checking account number and that gives you enough to write checks in their name. Know their credit-card number and expiration date and you've got enough to run most credit-card transactions. Just knowing the name and checking account number gives you enough to submit an electronic check against their account (you'll have to move fast to get the money out of your account and disappear before they notice the discrepancy, but if you've got that forged driver's license you can probably open a throwaway account easily enough).
Looking at it, a name and date and place of birth seems to be enough in most cases to get an official, certified birth certificate for that person sent to you. Just make sure to pay by money order, not credit card. A birth certificate's a stepping-stone to a lot of... interesting things.
I think, IIRC, that the owner of Eolas has connections to the University of California and to open-source in general. I think one of the things Microsoft is worried about here is that, rather than going after everyone, Eolas might come to terms with the open-source browsers while, at the same time, excercising their right as patent-holder to refuse to license the patent to Microsoft for future use. I don't know that that's a realistic possibility, but it'd certainly be entertaining.
Your last sentence is the catch, though. All that's needed to make IBM's counterclaims and RedHat's claims (the Lanham Act onesin particular) a slam dunk is an admission by SCO that they didn't have evidence at the very start. Nothing less will clear IBM's reputation sufficiently (as far as IBM's concerned), and SCO can't make that admission without leaving themselves defenseless to the claims against them. Even if it never gets to the point of criminal charges, the civil judgements alone will bankrupt the company (and open the executives including McBride to shareholder/investor lawsuits).
The main thing to remember is that at this point merely a ruling that IBM has all rights to the code isn't enough for IBM. They want/need a ruling that there was never any question at any point that they had all rights to the code. That's what their PSJ motion asked for, it's what they're virtually guaranteed to get once discovery's over, and I don't think they'll settle for less at this point.
At this point, though, IBM's not interested in any settlement that doesn't include an admission by SCO that they never had any evidence. IBM does too much business in the government and financial sectors to allow any hint of a question to exist about whether they'll honor their contracts. Plus, some of SCO's accusations touch on ages-old bits of IBM's mainframe core, and again IBM can't permit any hint of a question about their ownership of that because it's just too central to their business.
Except that SCO can't feasibly cut and run. First, there's IBM's counterclaims. Their admission that they didn't have a case won't dismiss those counterclaims, but it will make IBM's proving them a slam-dunk and the penalties there are more than SCO's got in available assets. Then there's the RedHat case, and if SCO admits to not having any case in the IBM case they virtually guarantee RedHat a win. Again, RedHat's claims would be ruinous. And then there's the AutoZone case, and if SCO abandons the IBM case AutoZone's sure to demand costs in their case. In short, SCO's currently backed into a corner where the only option that lets them survive at all as a company is to fight to the bitter end and pray for a miracle. It's pretty clear right now that the only way they'll win is if a large chunk of the judiciary suddenly goes insane, but that's still a better chance for survival than any of the other options so SCO's taking it.
I think Cohen's reacting in part to the Grokster decision. There and in Betamax it came down to two points: whether legal uses existed and whether the maker encouraged illegal uses or not. For a while, if the RIAA tried to come after the BitTorrent protocol itself on the first point they'd've had to overcome the use of BitTorrent to distribute things like Linux distributions (which is a perfectly legal use). Now if they try to use the same arguments against Cohen that they used against Grokster, arguing he's encouraging illegal uses himself, they're going to have to overcome this contract with the MPAA that binds him to doing exactly the opposite. I think he's being a very smart cookie, looking at the legal arguments people like the RIAA might use to attack him as creator of the protocol and reference implementation and making sure he's got as many legal obstacles in any attacker's way as possible.
That's almost any restaurant. Most of them get "restaurant blend" coffee from places like Folgers or Hills Brothers. Anything that out of the bag is a mix of light brown and tan is not good coffee.
Neither. Company called Flying J, did mostly commercial truckstops and fuel.
Hint, Rogers: Usenet != alt.binaries.*.
Far from it. The CEO was a bit stuck on dress, but not to the point of letting it override common sense or a million or so dollars a year in revenue. Of course it might've been another matter if the equipment hadn't worked perfectly for the demo, but I had no intention of letting that happen.
I eventually did leave the company, but it was 4 years later and because I had an offer that I liked a lot better (by that point I was getting real tired of Utah).
I had the CEO of a company I was working at start to gripe about my ignoring the dress code. I pointed at the pile of dirt and dust and dead insects that'd fallen out of the ceiling tile I'd pulled aside to work up in there and asked him if he was willing to get into that wearing his suit? He said no way, it was too expensive to ruin. I asked him if he was going to pay if I ruined my good clothes in there? He said no. "Then why should I? Now, can I get back to finding and fixing this wiring problem, or do you want the demo you're doing this afternoon, the one you said was critical to the company's success this year, to flop when none of the stuff you want to show off actually works?".
Which are, at least to me, just as easily spotted by the opening brace, or the changed indentation on the next line. Or by the font change for the keyword with any decent editor.
And grep or regexp search in Emacs recognize font changes how? :) The distinction is as much for "make it easy to programmatically find all occurrences of a call to f(...) without getting false hits on "if ( ... )"" as it is for "let a human pick out the if statements".
As someone with 20+ years of professional programming under my belt, a lot of it doing maintenance and enhancement of existing code, I'll say this: most of what's considered "coding standards" doesn't much matter. Indentation, brace positioning, type prefixes on variables, underlines vs. StudlyCaps, capitalization in general, most competent programmers can pick up on any variation quickly. The few things that count are more general:
Robert Morris didn't intend his little worm program to spread as widely as it did, but none of the companies and universities whose networks were shut down by the Morris Worm in 1988 cared about intentions. They only cared about the fact that the worm killed their networks. When Sony's software starts playing games with my system I don't care what their intentions were, only what the results are.
That's not a typical modern server or end user application.
You mean a modern network server doesn't have to read data from it's incoming connections? News to me, every one I've worked on has that as one of it's primary tasks. And it can't process the data until it's read it (or at least a sufficient portion of it to be able to figure out what to do next). Now, you can get fancy by trying to multiplex multiple connections in a single thread, but it's much simpler to spawn one thread of execution for each connection. You've got enough complexity already that you don't need to go creating any more for yourself.
That most programs today aren't GUI applications where the UI should not be *blocked* whilst some request is processed?
Modern GUI applications are message-driven. It's the message-processing loop that needs to never block. If you look, you'll find that 90% of the code in that GUI application is plain old traditional synchronous code to handle each type of message. Only a small portion in the message loop actually deals with controlling multiple threads.
As an example, if a GUI event triggers a time-consuming compute process, I can do two things. One, I can spawn off a thread to do the compute job and signal me when it's done. Two, I can write the data block down a pipe and let another thread or process deal with it, after having set a monitor on the pipe so I'll get a message when data's available on it. When the data-available message comes in, I snarf the results back from the pipe and do what needs done with them. Depending on how I implement the compute job there may be a layer to handle multiple incoming requests and fire off compute jobs, but the big function that actually does the crunching will be plain old single-threaded synchronous code and I'll let the system scheduler handle multi-tasking between the various jobs running at any given time. And on a Unix system where fork/exec is relatively cheap, why waste development time on a complex multi-threaded compute program when I can design a simple single-threaded one that reads it's input from standard input (connected to the incoming pipe) and writes it's output to standard output (connected to the outgoing pipe) and is pretty much immune to memory leaks, memory corruption and a host of other problems caused by other threads of execution in the same address space. On a modern Unix this'll probably handle 50 or so forks/second, and I've the option of doing pre-forking and having one instance handle multiple requests before terminating which should net me a hundred or so requests/second easily. By my standards that's hideously slow, but it's more than sufficient for an awful lot of applications. Especially in user-interface applications, because humans simply can't handle hundreds of operations per second.
You're misreading. It's not 90% of the problems out there, it's 90% of the code in a given program that's synchronous. Take, for example, the process of reading data from a single input source and processing it. With no other input sources to look at, and no processing that doesn't require the data you're trying to read, exactly what can the code do while the read's completing? If it can't do anything, then doing the read in it's own thread is pointless. You incur the overhead of creating a thread, and then the parent simply blocks until the child thread completes. Less overhead to simply do the read in the same thread as a simple function call. When calculating the sine of an argument, what do you gain from doing that function in it's own thread since the caller needs the result before it can continue with whatever calculation it's doing? Most of a program is like that: the caller can't proceed until the function it's called returns it's results, so running the called function in a seperate thread doesn't actually result in any parallelization.
As for what I've been writing, the last decade or so it's been primarily highly-parallel high-performance applications. Juggling a few dozen serial I/O channels with sub-millisecond response times on each channel, with a mix of polled and non-polled protocols. Breaking that one down to one single-threaded process per I/O channel and using message-based IPC to pass data between the I/O processes and the main program roughly tripled it's capacity while slashing code complexity by an order of magnitude. Another one involved a network server capable of handling several hundred simultaneous requests and several thousand requests per second sustained. Shared config data was the big constraint there, we could've cut 20% in interlock overhead alone if we could've gone to seperate processes and improved stability in the process, but while Linux could spawn processes that fast Solaris couldn't (we needed to support both) and with a gig or so of config data we couldn't afford the memory split that happened when we did a config reload under maximum load. I think it took my replacement 6 months or so to finally realize that no, he can't short-cut the interlocking even if it does work OK that way in testing, what works with 1-2 simultaneous threads will not work with 1-2 hundred.
Even between threads you've got overhead, either true context-switch overhead (on systems with a 1:1 thread-to-KSE mapping) or a similar amount of thread-scheduler overhead (on systems with an N:1 thread-to-KSE mapping). Note that multiple processes will also use all available CPUs in a multi-processor system, and on some systems threads can only> execute on the single CPU their KSE is currently running on, so depending on your threads implementation a multi-threaded app may or may not use all CPUs.
As for the first part, as I noted a lot of "shared" memory is read-only as far as the child's concerned. The only real issue with seperate processes is the potential for a massive memory split if one process suddenly updates the majority of that "read-only" memory (eg. reloading of configuration data). Where you have lots of memory shared that doesn't involve pointer-based data structures, shared memory will get you what you need without the need for fully-shared address space (which means your various processes are protected from heap corruption by their siblings, among other things). There are times you need the entire address space shared, but IMHO they aren't nearly as common as they're made out to be and the problems of fully-shared address space are well-known and not insignificant.
As far as why you don't make every function a process, for the same reason you don't make every function a thread: the vast majority of a program is not parallelizable. Parallel threads of execution, be they threads or processes, are applicable when the parent can fire off the child and go do something else while the child executes. If the only thing the parent can do at that point is wait for the child to finish, it's more efficient to simply do a call within the same thread of execution.
Forked processes do share memory (at least until it's modified). What you get with a shared memory space is the requirement for a lot of mutexing to avoid multiple updates, and a massively increased chance of corrupting memory across all threads. Been there, done that, in spades. Having done several massively-multi-threaded applications, my evaluation is that 90% of the time you're probably better off avoiding memory-based communication entirely in favor of message-passing through pipes, sockets or similar IPC mechanisms. That has the advantage of also removing most of the interlocking needed for high-performance shared-memory designs. The exceptions are when you've got a large amount of common configuration data that all tasks need access to. Using mmap() is a better way of handling that than sharing the entire address space, but when you've got pointer-based structures the workarounds for variable base addresses can get hairy enough to make shared-address-space the better option.
Just my opinion, but after 25 years of making machines with bits for brains do things I'm inclined to trust my own judgement.
You need to upgrade to a current version of GDB, then. Anything recent (within the last year or two) handles threads fine. I've used it to debug applications with a couple of hundred simultaneously-active threads without any problems.
Exactly. NT got it's process model from VMS, and process creation was a very heavyweight operation. Unix, by contrast, had a very lightweight process creation operation. Hence NT needed threads to provide a faster alternative to processes, while Unix (whose processes were almost as cheap to create as NT threads) didn't really need threads for anything other than a marketing checklist (about the only thing Unix threads get you that processes don't is fully-shared address space, and I'd argue that's often more a problem than an advantage).
First, IPv6 is even easier to set up. You don't need DHCP for automatic address assignment, a device can get it's network number via broadcast and assign it's own address based on MAC address. Literally plug-and-play.
The way IPv6 addresses are (supposed to be) assigned makes NAT unneccesary. This makes things like instant-messaging and P2P protocols, where clients act as servers and really need public addresses to work smoothly, much easier to deal with. No kludging forwarding rules.
NAT can still be used where appropriate. You'll simply need it less often.
At the routing level it simplifies things because the address hierarchy can mirror the physical topology. This is invisible to end users, but it's a major major win at the ISP and backbone level. Especially when devices can be configured to automatically adapt to changing network numbers, which essentially eliminates network renumbering when connections change.
IPv4 and IPv6 seem to play together well. My desktop system is a hybrid IPv4/6 box defaulting to IPv6, my central router's IPv4-only. On the desktop box all the apps see IPv6-based sockets and the appropriate IPv4-over-IPv6 addresses, the IPv4 portions of the network see plain IPv4 traffic.
As a final note, when I replace my desktop and rebuild the central router, I'm going to go to an IPv6-based network with IPv4 support being secondary. Even with the need to NAT to a single IPv4 address on the external connection, I expect the whole thing to be relatively seamless.
Actually that would be wrong. California never adopted the UCITA, so absent any other agreement the transaction's governed by the Uniform Commercial Code. I never signed any agreement to only license the software before the sale, so an over-the-counter sale occurred per the UCC. I own the copy I bought under those rules. I'd also note that the appeals court considered the same logic you're using and explicitly rejected it in their ruling when they discussed whether formal title was needed or not.
My thought: Microsoft is trying to get Federal rules that they can live with and that'll override more restrictive state rules. Take a look at opt-in vs. opt-out in their proposal. They advocate opt-in for a very limited class of data that they know the general public's getting touchy about, and I'll bet they make that a headline point. But for all other classes of data, they want opt-out enshrined in law in a way that prevents any state from requiring opt-in across the board. And once this is nailed down in Federal law, it'll be all but impossible to get it changed later no matter what happens.
I think that's Microsoft's strategy: cave in on the few points the public's riled up about right now, while simultaneously nailing down favorable terms everywhere else.
I think the objection isn't to the taxation so much as to the fact that you could wind up liable for taxes on the same income in two states at the same time, which seems fundamentally unreasonable.
Well, for total identity theft you probably need the SSN. However, a lot can be done without the SSN. Given someone's name, address and birthdate you can get a forged driver's license that'll fool most clerks. If you also have their driver's license number, it'll fool most electronic checking systems as well. Know their checking account number and that gives you enough to write checks in their name. Know their credit-card number and expiration date and you've got enough to run most credit-card transactions. Just knowing the name and checking account number gives you enough to submit an electronic check against their account (you'll have to move fast to get the money out of your account and disappear before they notice the discrepancy, but if you've got that forged driver's license you can probably open a throwaway account easily enough).
Looking at it, a name and date and place of birth seems to be enough in most cases to get an official, certified birth certificate for that person sent to you. Just make sure to pay by money order, not credit card. A birth certificate's a stepping-stone to a lot of... interesting things.
I think, IIRC, that the owner of Eolas has connections to the University of California and to open-source in general. I think one of the things Microsoft is worried about here is that, rather than going after everyone, Eolas might come to terms with the open-source browsers while, at the same time, excercising their right as patent-holder to refuse to license the patent to Microsoft for future use. I don't know that that's a realistic possibility, but it'd certainly be entertaining.
Your last sentence is the catch, though. All that's needed to make IBM's counterclaims and RedHat's claims (the Lanham Act onesin particular) a slam dunk is an admission by SCO that they didn't have evidence at the very start. Nothing less will clear IBM's reputation sufficiently (as far as IBM's concerned), and SCO can't make that admission without leaving themselves defenseless to the claims against them. Even if it never gets to the point of criminal charges, the civil judgements alone will bankrupt the company (and open the executives including McBride to shareholder/investor lawsuits).
The main thing to remember is that at this point merely a ruling that IBM has all rights to the code isn't enough for IBM. They want/need a ruling that there was never any question at any point that they had all rights to the code. That's what their PSJ motion asked for, it's what they're virtually guaranteed to get once discovery's over, and I don't think they'll settle for less at this point.
At this point, though, IBM's not interested in any settlement that doesn't include an admission by SCO that they never had any evidence. IBM does too much business in the government and financial sectors to allow any hint of a question to exist about whether they'll honor their contracts. Plus, some of SCO's accusations touch on ages-old bits of IBM's mainframe core, and again IBM can't permit any hint of a question about their ownership of that because it's just too central to their business.
Except that SCO can't feasibly cut and run. First, there's IBM's counterclaims. Their admission that they didn't have a case won't dismiss those counterclaims, but it will make IBM's proving them a slam-dunk and the penalties there are more than SCO's got in available assets. Then there's the RedHat case, and if SCO admits to not having any case in the IBM case they virtually guarantee RedHat a win. Again, RedHat's claims would be ruinous. And then there's the AutoZone case, and if SCO abandons the IBM case AutoZone's sure to demand costs in their case. In short, SCO's currently backed into a corner where the only option that lets them survive at all as a company is to fight to the bitter end and pray for a miracle. It's pretty clear right now that the only way they'll win is if a large chunk of the judiciary suddenly goes insane, but that's still a better chance for survival than any of the other options so SCO's taking it.